package com.bruce.spring.http.service.cgroup;

import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * Cgroup v2 容器CPU使用率提供者
 * 仅通过 user_usec + system_usec 计算总CPU耗时
 */
public class CgroupV2ProviderWithChannel extends CgroupV2BaseProvider implements Closeable {

    private final FileChannel statChannel;
    // 4KB缓冲区，确保容纳cpu.stat内容
    private final ByteBuffer statBuffer = ByteBuffer.allocate(2048);

    public CgroupV2ProviderWithChannel() throws IOException {
        // 打开cpu.stat通道（复用，高频读取）
        this.statChannel = FileChannel.open(Paths.get(cpuStatPath), StandardOpenOption.READ);
    }


    /**
     * 读取当前CPU累计时间（纳秒）
     * 仅通过 user_usec + system_usec 计算
     */
    @Override
    public long getCurrentCpuTime() throws IOException {
        long userUsec = 0;
        long systemUsec = 0;

        statBuffer.clear();
        statChannel.position(0);
        // 读取cpu.stat内容
        int bytesRead = statChannel.read(statBuffer);
        if (bytesRead <= 0) {
            throw new IOException("cpu.stat文件内容为空");
        }
        statBuffer.flip();
        // 按行解析
        String content = new String(statBuffer.array(), 0, bytesRead);
        String[] lines = content.split("\n");

        for (String line : lines) {
            line = line.trim();
            if (line.isEmpty()) continue;

            // 仅匹配用户态和内核态耗时字段
            if (line.startsWith(USER_USEC)) {
                int spaceIndex = line.indexOf(SPACE);
                String valueStr = line.substring(spaceIndex + 1).trim();
                userUsec = parseLongSafely(valueStr);
            } else if (line.startsWith(SYSTEM_USEC)) {
                int spaceIndex = line.indexOf(SPACE);
                String valueStr = line.substring(spaceIndex + 1).trim();
                systemUsec = parseLongSafely(valueStr);
            }

            // 已获取两个字段，提前退出循环
            if (userUsec > 0 && systemUsec > 0) {
                break;
            }
        }

        // 校验并计算总耗时
        if (userUsec == 0 && systemUsec == 0) {
            throw new IOException("未从cpu.stat解析到有效CPU时间（user_usec和system_usec均为0）");
        }

        // 微秒转纳秒
        return (userUsec + systemUsec) * 1000;
    }

    /**
     * 安全解析长整数，避免格式错误
     */
    private long parseLongSafely(String valueStr) {
        try {
            return Long.parseLong(valueStr);
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    /**
     * 关闭文件通道，释放资源
     */
    @Override
    public void close() throws IOException {
        statChannel.close();
    }
}